#ifndef MCMC_PLE_H
#define MCMC_PLE_H

#include "mcmcHistogram.h"
#include "Matrix.h"
#include "mcRaster.h"
#include "mcmcSparseMatrix.h"
#include "mcmcImageFilters.h"

////////////////////////////////////////////////////////////////////////
// for saving histogram or responses for one value at a certain position
class MCMC_RespChange
{
public:
	MCMC_RespChange();
	~MCMC_RespChange();

	void	AllocateSpace(const int size);
	void	SaveToFile(ofstream &file);
	void	ReadFromFile(ifstream &file);

public:
	int			num_resp;
	char		*pdata;
};

////////////////////////////////////////////////////////////////////////
class MCMC_PixelResp
{
public:
	MCMC_PixelResp();
	~MCMC_PixelResp();
	void	Free(void);
	void	AllocateSpace(const int size);
	void	SaveToFile(ofstream &file);
	void	ReadFromFile(ifstream &file);

public:
	MCMC_RespChange		*presps;
	int					num_value;
};


////////////////////////////////////////////////////////////////////////
class MCMC_PLE_Resp
{
public:
	MCMC_PLE_Resp();
	~MCMC_PLE_Resp();

	void			SetFiter(MCMC_FilterBank &filter_bank, const int ifilter,
							const int rows, const int cols,
							const double low_input, const double high_input, const double delta_input,
							const double low_output, const double high_output, const double delta_output);
	void			ComputeResponse(const int row_top, const int row_bottom, const int col_left, const int col_right);
	void			SaveToFile(ofstream &file);
	void			ReadFromFile(ifstream &file);
	inline	bool	AsHistogram(void){return bRememberAsHist;};

public:
	SimpleMatrix<MCMC_PixelResp>	mx_filter_resp;

protected:
	MCMC_FilterBank		*p_filter_bank;
	int					nfilter;
	bool				bRememberAsHist;
	Histogram			hist_ref_input;			// for referencing the possible values of pixel, not for hist under this filter
	Histogram			hist_ref_output;
	irmm_Rect			rect_bound;				// current patch
};


typedef  mcmcVector<double> Vector_Double;

////////////////////////////////////////////////////////////
class FRAME_One_Channel
{
public:
	FRAME_One_Channel();
	~FRAME_One_Channel();

	virtual void	Set(MCMC_FilterBank &filter_bank, const bool bComputeInAdvance,
		                const int biggest_row_size, const int biggest_col_size);
			void	UpdateHistogramSyn(void);
			void	UpdateHistogramSynTemp(const double prob, const double value, const int row, const int col);
			bool	UpdateBeta(const double d);
			void	ClearHistogramSyn(void);
			void	ClearHistogramSynTemp(void);
			void	FilteringOnNewImage(Raster<double> &image);
	inline	void	UpdateFilterRespAtOneSite(const int j, const int i, const double value){pfilter_bank->UpdateFilterRespAtOneSite(j,i,value);};
	inline	int		NumFilter(void){return pfilter_bank->NumFilter();};
			void	SaveRespHistToFile(ofstream &file);
			void	ReadRespHistFromFile(ifstream &file);
			double	EnergyFromHist(const int row, const int col, const int index_value);

	inline	double	GetLow(void){return low_value;};								// the lowest possible value
	inline	double	GetHigh(void){return high_value;};								// the highest possible value
	inline	double	GetDelta(void){return delta;};
	inline	int		GetIndex(const double value){return histogram_ref_input.GetIndex(value);};
			void	ComputeEnergyAtEachValue(const int j, const int i);
			void	SaveTempEnergy(const int row, const int col);	// from the pre-computed histogram
			void	ComputeResponse(const int row_top, const int row_bottom, const int col_left, const int col_right);
	inline	int		NumValue(void){return histogram_ref_input.count;}
	inline	bool	ValidIndex(const int k){return vc_energy.Valid(k);};
	inline  double	GetValueIndex(const int k){return histogram_ref_input.GetValueIndex(k);};

public:
	SimpleMatrix<Histogram>		vc_histogram_obs;
	SimpleMatrix<Gibbs_B>		vc_B;
	MCMC_FilterBank				*pfilter_bank;
	MCMC_PLE_Resp				*p_ple_resp;
	mcmcVector<double>				vc_energy;
	Histogram					histogram_ref_input;

protected:
	SimpleMatrix<Histogram>		vc_histogram_syn;
	SimpleMatrix<Histogram>		vc_histogram_syn_temp;
	int							num_filter;
	double						low_value,high_value,delta;
	RF_uniform					rf_rand_beta;		// when some bins are not sampled, a randomness is needed
};
























#endif
